import { EventEmitter } from 'events';
import * as msgpack from 'notepack.io';
import * as shortid from 'shortid';
import * as WebSocket from 'ws';
import { Room } from '../../src/Room';
import { LocalPresence } from './../../src/presence/LocalPresence';

export class Client extends EventEmitter {

  public id: string;
  public messages: any[] = [];
  public readyState: number = WebSocket.OPEN;

  constructor(id?: string) {
    super();
    this.id = id || null;

    this.on('close', () => {
      this.readyState = WebSocket.CLOSED;
    });
  }

  public send(message) {
    this.messages.push(message);
  }

  get lastMessage() {
    return msgpack.decode(this.messages[ this.messages.length - 1 ]);
  }

  public close() {
    // this.emit('close');
  }

}

export function createEmptyClient(): any {
  return new Client();
}

export function createDummyClient(options?: any): any {
  const client = new Client(shortid.generate());
  (client as any).options = options;
  return client;
}

// tslint:disable-next-line:max-classes-per-file
export class DummyRoom extends Room {
  constructor() {
    super(new LocalPresence());
  }

  public requestJoin(options) {
    return !options.invalid_param;
  }

  public onInit() { this.setState({}); }
  public onDispose() {}
  public onJoin() {}
  public onLeave() {}
  public onMessage() {}
}

// tslint:disable-next-line:max-classes-per-file
export class RoomWithError extends Room {
  constructor() {
    super(new LocalPresence());
  }
  public onInit() { this.setState({}); }
  public onDispose() {}
  public onJoin() {
    (this as any).iHaveAnError();
  }
  public onLeave() {}
  public onMessage() {}
}

// tslint:disable-next-line:max-classes-per-file
export class DummyRoomWithState extends Room {
  constructor() {
    super(new LocalPresence());
    this.setState({ number: 10 });
  }

  public requestJoin(options) {
    return !options.invalid_param;
  }

  public onInit() {}
  public onDispose() {}
  public onJoin() {}
  public onLeave() {}
  public onMessage() {}
}

// tslint:disable-next-line:max-classes-per-file
export class DummyRoomWithTimeline extends Room {
  constructor() {
    super(new LocalPresence());
    this.useTimeline();
  }

  public requestJoin(options) {
    return !options.invalid_param;
  }

  public onInit() { this.setState({}); }
  public onDispose() {}
  public onJoin() {}
  public onLeave() {}
  public onMessage() {}
}

// tslint:disable-next-line:max-classes-per-file
export class RoomVerifyClient extends DummyRoom {
  public patchRate = 5000;
  public onJoin() {}
}

// tslint:disable-next-line:max-classes-per-file
export class RoomVerifyClientWithLock extends DummyRoom {
  public patchRate = 5000;

  public async verifyClient() {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(true), 100);
    });
  }

  public onJoin() {
    this.lock();
  }

}
